package com.ml.loan.common.thread;

import com.google.common.util.concurrent.ThreadFactoryBuilder;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.MDC;

import java.util.Map;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * 异步任务管理器
 *
 * @author Mickey
 * @date 2022/8/24 13:32
 */
@Slf4j
public class AsyncTaskManager {

    //核心线程数
    private static final int CORE_SIZE = 10;

    //最大线程数
    private static final int MAX_SIZE = 50;

    //队列数
    private static final int QUEUE_SIZE = 1000;

    private AsyncTaskManager() {
    }

    private static AsyncTaskManager me = new AsyncTaskManager();

    public static AsyncTaskManager me() {
        return me;
    }

    /**
     * 提交任务到线程池
     *
     * @author Mickey
     * @date 2022/8/24 11:57
     */
    public void submit(Runnable r) {
        final Map<String, String> copyOfContextMap = MDC.getCopyOfContextMap();
        taskAsync.submit(() -> {
            try {
                if (copyOfContextMap != null) {
                    MDC.setContextMap(copyOfContextMap);
                }
                r.run();
            } finally {
                MDC.clear();
            }
        });
    }

    /**
     * 异步线程池
     *
     * @author Mickey
     * @date 2022/8/24 13:35
     */
    private ExecutorService taskAsync = new ThreadPoolExecutor(CORE_SIZE,
            MAX_SIZE,
            60L,
            TimeUnit.SECONDS,
            new ArrayBlockingQueue<>(QUEUE_SIZE),
            new ThreadFactoryBuilder().setNameFormat("Async-Task-Executor-%d").build(),
            (r, executor) -> log.error("async task is error rejected, runnable: {}, executor: {}", r, executor)) {
        @Override
        protected void afterExecute(Runnable r, Throwable t) {
            super.afterExecute(r, t);
            Threads.printException(r, t);
        }
    };

}
